package com.websql.yousql.annotation.operationLog;

import com.alibaba.fastjson.JSONObject;
import com.websql.yousql.annotation.OperationLog;
import com.websql.yousql.config.dataSource.DataSourceProviderImpl;
import com.websql.yousql.config.dataSource.RoutingDataSourceContext;
import com.websql.yousql.config.sqlGetter.SqlIntercept;
import com.websql.yousql.dao.ActionLogDao;
import com.websql.yousql.dao.ConnectionDao;
import com.websql.yousql.entity.ActionLog;
import com.websql.yousql.utils.HttpHeaderUtil;
import lombok.AllArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Aspect
@Component
@AllArgsConstructor
public class OperationLogAop {

    private final ActionLogDao actionLogDao;
    private final ConnectionDao connectionDao;
    private final HttpServletRequest request;
    private final TransactionTemplate tranTemplate;

    @Around(value = "@annotation(operationlog)")
    public void logAround(ProceedingJoinPoint p, OperationLog operationlog) throws Throwable {
        OperationType type = operationlog.action();
        p.proceed();
        switch (type) {
            case SELECT:
                select(p, operationlog);
                break;
            case INSERT:
                insert(p, operationlog);
                break;
            case UPDATE:
                update(p, operationlog);
                break;
            case DELETE:
                delete(p, operationlog);
                break;
            case LOGIN:
                login(p, operationlog);
                break;
            case LOGOUT:
                logout(p, operationlog);
                break;
        }
    }

    public void select(ProceedingJoinPoint p, OperationLog operationlog) {
        tranTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                String connId,database,action,table,sql,ipaddress,content;
                //切点方法的参数（1.database 2.dto）
                Object[] args = p.getArgs();
                Integer userId = null;//通过session获取
                final HashMap<String, String> hostAndPort = DataSourceProviderImpl.hostAndPort;
                database = String.valueOf(args[0]);
                action = operationlog.action().getType();
                table = operationlog.table();
                sql = JSONObject.toJSONString(SqlIntercept.sqlAndParam);//取mybatis的Executor执行器执行前的sql
                ipaddress = HttpHeaderUtil.getIpAddress(request);//aop获取请求头信息的响应ip
                content = operationlog.content();
                connId = connectionDao.getIdByUserAndIp(userId, hostAndPort.get("host"), hostAndPort.get("port"));
                ActionLog op = new ActionLog(){{
                    setUserId(userId);
                    setConnId(connId);
                    setDatabaseName(database);
                    setTableName(table);
                    setAction(action);
                    setSqlStr(sql);
                    setIpaddress(ipaddress);
                    setCreateTime(new Date());
                    setContent(content);
                }};
                RoutingDataSourceContext.setDataSourceRoutingKey("YouSQL");
                actionLogDao.insertOperationLog(op);
            }
        });
    }

    public void insert(ProceedingJoinPoint p, OperationLog operationlog) {
        tranTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                String userId,connId,database,action,table,sql,ipaddress,content;
                //切点方法的参数（1.database 2.dto）
                Object[] args = p.getArgs();
                userId = "";//通过session获取
                DataSourceProviderImpl sourceProvider = new DataSourceProviderImpl();
//                connId = connectionDao.getIdByUserAndIp(userId, sourceProvider.getHost(), sourceProvider.getPort());
                database = String.valueOf(args[0]);
                action = operationlog.action().getType();
                table = operationlog.table();
                sql = "sql"+ SqlIntercept.sqlAndParam.get("sql") +"\nparam:"+ SqlIntercept.sqlAndParam.get("param");//取mybatis的Executor执行器执行前的sql
                ipaddress = HttpHeaderUtil.getIpAddress(request);//aop获取请求头信息的响应ip
                content = operationlog.content();
                ActionLog op = new ActionLog(){{
 //                   setUserId(userId);
 //                   setConnId(connId);
                    setDatabaseName(database);
                    setTableName(table);
                    setAction(action);
                    setSqlStr(sql);
                    setIpaddress(ipaddress);
                    setCreateTime(new Date());
                    setContent(content);
                }};
                actionLogDao.insertOperationLog(op);
            }
        });
    }

    public void update(ProceedingJoinPoint p, OperationLog operationlog) {
    }

    public void delete(ProceedingJoinPoint p, OperationLog operationlog) {
    }

    public void login(ProceedingJoinPoint p, OperationLog operationlog) {
    }

    public void logout(ProceedingJoinPoint p, OperationLog operationlog) {
    }


}
